<?php
namespace App\Services\ThirdPayments\Recharge;

use App\Exceptions\RechargeGatewayException;
use App\Facades\RechargeLog;
use App\Lib\Code;
use App\Lib\PaymentMap;
use App\Lib\ThirdPartyMap;
use App\Models\RechargeOrder;
use App\Services\ThirdPayments\Contracts\Actions\HrefRedirectAction;
use App\Services\ThirdPayments\Contracts\QRCapable;
use App\Services\ThirdPayments\Contracts\RechargeBaseAbstract;
use App\Services\ThirdPayments\Contracts\WAPable;

class ESDPayment extends RechargeBaseAbstract implements WAPable
{
    protected $gw_pay = 'http://rui.amy0807.com/pay/payment';
    protected $gw_query = 'http://rui.amy0807.com/pay/payquery';

    public function callback(array $data)
    {
        // TODO: Implement callback() method.
        if ($this->veryCallbackSign($data)) {
            if ($data['status'] == 0) {
                if ($data['result_code'] == 0) {
                    return true;
                }
            }
        }
        return false;
    }

    public function veryCallbackSign(array $data)
    {
        // TODO: Implement veryCallbackSign() method.
        $sign = $data['sign'];
        array_forget($data, 'sign');
        ksort($data);
        $signStr = '';
        foreach ($data as $k => $v) {
            $signStr .= $k . '=' . $v . '&';
        }
        $signStr .= 'key=' . $this->getMchKey();
        $parseSign = strtoupper(md5($signStr));
        if ($parseSign == $sign) {
            return true;
        } else {
            return false;
        }
    }

    public function getOrderNoFromCallback(array $data)
    {
        // TODO: Implement getOrderNoFromCallback() method.
        return $data['shoporderId'];
    }

    public function getThirdNoFromCallback(array $data)
    {
        return $data['orderid'];
    }

    /**
     * @return mixed
     */
    public function getIdentify(): string
    {
        // TODO: Implement getIdentify() method.
        return ThirdPartyMap::ESD;
    }

    /**
     *  needs child to achieve
     */
    public function initPaymentMap(): array
    {
        // TODO: Implement initPaymentMap() method.
        return [
            PaymentMap::WX => 'HFWXPay',
            PaymentMap::ALI_WAP => 'HFAliPayH5',
            PaymentMap::WX_WAP => 'YHXFWXWAP',
            PaymentMap::QQ => 'HFQQPay',
            PaymentMap::QQ_WAP => 'YHXFQQWAP'
        ];
    }

    public function query(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement query() method.
        $this->setParameter('merchantid', $this->getMchId());
        $this->setParameter('shoporderid', $rechargeOrder->plat_no);
        $this->setParameter('nonce_str', createNonceStr());
        $this->setParameter('sign', $this->querySign());
        $res = curlHttp($this->getGwQuery(), json_encode($this->getParameters()), 'post');
        if ($res['http_code'] == 200) {
            $resData = json_decode($res['body'], true);
            if ($resData['status'] == 0) {
                return true;
            }
        }
        return $res['body'];

    }

    public function bankHref(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement bankHref() method.
    }

    public function scanCode(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement scanCode() method.
        $this->initParameters($rechargeOrder);
        $data = json_encode($this->getParameters());
        $res = curlHttp($this->getGwPay(), $data, 'post');
        $qr_code = '';
        if ($this->curlResVerify($this, $res)) {
            $resData = json_decode($res['body'], true);
            $rechargeOrder->third_return = $res['body'];
            $rechargeOrder->save();
            if ($resData['status'] == 0) {
                if ($resData['result_code'] == 0) {
                    $qr_code = $resData['code_url'];
                }
            } else {
                throw new RechargeGatewayException($this, $res['body'], $resData['message'], Code::RECHARGE_THIRD_LOG);
            }
        }
        return $qr_code;
    }

    public function paySign(): string
    {
        // TODO: Implement paySign() method.
        $params = $this->getParameters();
        array_forget($params, 'sign');
        ksort($params);
        $signStr = '';
        foreach ($params as $k => $param) {
            $signStr .= $k . '=' . $param . '&';
        }
        $signStr .= 'key=' . $this->getMchKey();
        $sign = strtoupper(md5($signStr));
        $this->log_str .= '[originSignStr]:'.$signStr ." \r\n [sign]:".$sign;
        return $sign;
    }

    public function querySign(): string
    {
        // TODO: Implement querySign() method.
        $parameters = $this->getParameters();
        ksort($parameters);
        $signStr = '';
        foreach ($parameters as $k => $parameter) {
            $signStr .=  $k . '='. $parameter . '&';
        }
        $signStr .= 'key='.$this->getMchKey();
        return strtoupper(md5($signStr));
    }

    public function showSuccess(): string
    {
        // TODO: Implement showSuccess() method.
        return 'success';
    }

    public function initParameters(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement initParameters() method.
        $mchData = $rechargeOrder->order_data;
        $this->setParameter('version', 'v1.0');
        $this->setParameter('service', $this->getPaymentMap($mchData['recharge_type']));
        $this->setParameter('signtype', 'MD5');
        $this->setParameter('charset', 'UTF-8');
        $this->setParameter('merchantid', $this->getMchId());
        $this->setParameter('shoporderId', $rechargeOrder->plat_no);
        $this->setParameter('totalamount', $rechargeOrder->order_amt);
        $this->setParameter('productname', $mchData['body'] ?? $rechargeOrder->plat_no);
        $this->setParameter('goods_tag', $this->setRemark($rechargeOrder));
        $this->setParameter('notify_url', $this->getCallbackUrl());
        $this->setParameter('callback_url', $this->getReturnUrl());
        $this->setParameter('nonce_str', createNonceStr());
        $this->setParameter('sign', $this->paySign());
    }

    public function wapReq(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement wapReq() method.
        $this->initParameters($rechargeOrder);
        $data = json_encode($this->getParameters());
        $res = curlHttp($this->getGwPay(), $data, 'post');
        $qr_code = '';
        if ($this->curlResVerify($this, $res)) {
            $resData = json_decode($res['body'], true);
            $rechargeOrder->third_return = $res['body'];
            $rechargeOrder->save();
            if ($resData['status'] == 0) {
                if ($resData['result_code'] == 0) {
                    $qr_code = $resData['code_url'];
                }
            } else {
                throw new RechargeGatewayException($this, $res['body'], $resData['message'], Code::RECHARGE_THIRD_LOG);
            }
        }
        return new HrefRedirectAction($qr_code);
    }

    public function getOrderAmtFromCallback(array $data)
    {
        // TODO: Implement getOrderAmtFromCallback() method.
        return $data['total_fee'];
    }
}
